﻿using System;
using System.Linq;
using System.Reflection;
using Myotragus.Data.Domain;
using Myotragus.Data.Emit;
using Myotragus.Data.Tests.Utils;
using NUnit.Framework;

namespace Myotragus.Data.Tests.Tests.Emit
{
	[TestFixture]
	public class DynamicAssemblyFixtures
	{
		[Test]
		public void InputValidation()
		{
			var name = FixturesHelper.CreateNameGenerator();
			var dyn = new DynamicAssembly(name);

			Assert.Throws<ArgumentNullException>(() =>
				dyn.DefineType(null, TypeAttributes.Public, null, null));
			Assert.Throws<ArgumentNullException>(() =>
				dyn.DefineType("Name", TypeAttributes.Public, null, null));
			Assert.DoesNotThrow(() =>
				dyn.DefineType("Name", TypeAttributes.Public, FixturesHelper.TypeOfObject, null));
		}

		[Test]
		public void GenerateAType()
		{
			var name = FixturesHelper.CreateNameGenerator();
			var dyn = new DynamicAssembly(name);

			var type = dyn.DefineType("TypeName", TypeAttributes.Public, FixturesHelper.TypeOfObject,
				new[] { FixturesHelper.TypeOfTestEntity });
			type.AddInterfaceImplementation(FixturesHelper.TypeOfTestEntity2);

			Assert.IsTrue(type.Interfaces.Contains(FixturesHelper.TypeOfTestEntity));
			Assert.IsTrue(type.Interfaces.Contains(FixturesHelper.TypeOfTestEntity2));

			foreach (var prop in FixturesHelper.TypeOfTestEntity2.GetProperties().Concat(
					FixturesHelper.TypeOfTestEntity.GetProperties()
				).Concat(
					typeof(IEntity<int>).GetProperties()
				))
			{
				type.DefineAutomaticProperty(prop.Name, prop.PropertyType);
			}

			type.DefineDefaultConstructor(MethodAttributes.Public);
			Assert.DoesNotThrow(() => type.CreateType());
		}
	}
}